package stud.mpgame.old.game;

import org.apache.mina.core.buffer.IoBuffer;
import org.apache.mina.core.session.IoSession;
import stud.mpgame.network.IMessageReceivedListener;
import stud.mpgame.network.Message;
import stud.mpgame.network.NetworkMonitor;
import stud.mpgame.network.UserObject;
import stud.mpgame.snapshot.ICommand;
import stud.mpgame.snapshot.ISnapshot;
import stud.mpgame.utils.ICloneable;

import java.util.ArrayList;
import java.util.List;

public class GameWorld extends UserObject implements IMessageReceivedListener, ISnapshot, ICloneable {

    private List< Player > players = new ArrayList< Player >();
    private NetworkMonitor networkMonitor;
    private int time;

    public GameWorld() {}

    public GameWorld(int time, NetworkMonitor networkMonitor) {
        this.time = time;
        this.networkMonitor = networkMonitor;
    }

    public void update(int delta) {
        for (Player player : players) {
            player.move(delta);
        }
    }

    public void addUser(Player player) {
        players.add(player);
    }

    public void removeUser(IoSession session) {
        Player currentPlayer = getUser(session);
        players.remove(currentPlayer);
    }

    private Player getUser(IoSession session) {
        for (Player player : players) {
            if (player.getSession().equals(session)) {
                return player;
            }
        }
        return null;
    }

    public void messageReceived(Message message) {
        IoSession session = message.getFirstSession();
        GameCommand gameCommand = (GameCommand) message.getUserObject(GameCommand.class);
        gameCommand.setTime(networkMonitor.nowTime());
        gameCommand.setSession(session);
        //todo exception
        this.getUser(session).applyGameCommand(gameCommand);
    }

    public void applyGameCommand(IoSession session, ICommand command) {
        GameCommand gameCommand = (GameCommand) command;
        this.getUser(session).applyGameCommand(gameCommand);
    }

    public String toString() {
        String result = "GameWorld: ";
        result += players.size() + " player(s):\n";
        for(Player player : players) {
            result += "id: " + player.getId();
            result += " x: " + player.getX();
            result += " y: " + player.getY();
            result += "\n";
        }
        return result;
    }

    @Override
    public void writeExternal(IoBuffer buffer, Message owner) {
    	buffer.putInt(players.size());
    	for(Player player : players) {
    	    player.writeExternal(buffer, owner);
    	}
    }

	public int getTime() {
		return time;
	}
	
	public void setTime(int time) {
		this.time = time;
	}

	public ISnapshot modelNext(int deltaTime, List< ICommand > commands) {
		GameWorld gameWorld = (GameWorld) getClone();
		gameWorld.setTime(getTime() + deltaTime);
		for (ICommand command : commands) {
			command.apply(gameWorld);
        }
        gameWorld.update(deltaTime);
		return gameWorld;
	}

	public ICloneable getClone() {
		GameWorld gameWorld = new GameWorld(time, networkMonitor);
		for(Player player : players) {
			gameWorld.players.add((Player) player.getClone());
		}
		return gameWorld;
	}

}